﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using SharePointBrowser.Data;
using System.Xml;
using System.Globalization;
using SharePointBrowser.UserControls;

namespace SharePointBrowser.Forms
{
    public partial class NewItem : Form
    {
        class ListItem
        {
            public string ID { get; set; }
            public string Name { get; set; }

            public override string ToString()
            {
                return ID + ";#" + Name;
            }
        }

        const int HPADDING = 5;

        private Dictionary<string, Control> fieldControls = new Dictionary<string, Control>();

        public string SiteUrl { get; set; }
        public string ListId { get; set; }
        public string ListName { get; set; }

        public NewItem()
        {
            InitializeComponent(); 
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            Cursor.Current = Cursors.WaitCursor;
            XmlNode list = SPAdapter.Instance.GetList(ListName, SiteUrl);
            XmlNodeList fields = list.SelectNodes("sp:Fields/sp:Field", SPAdapter.Instance.NamespaceManager);

            int y = 0;
            foreach (XmlNode field in fields)
            {
                if ((field.Attributes["Hidden"] == null || !Convert.ToBoolean(field.Attributes["Hidden"].Value)) &&
                    (field.Attributes["ReadOnly"] == null || !Convert.ToBoolean(field.Attributes["ReadOnly"].Value)))
                {
                    if (field.Attributes["Type"] != null && field.Attributes["Type"].Value == "Attachments")
                    {
                        continue;
                    }
                    Label lblField = new Label();
                    lblField.Text = field.Attributes["DisplayName"].Value;
                    lblField.Bounds = new Rectangle(HPADDING, y, ClientSize.Width - 2 * HPADDING, 32);
                    lblField.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                    Controls.Add(lblField);
                    y += lblField.Height;
                    switch (field.Attributes["Type"].Value)
                    {
                        case "Text":
                            TextBox txtField = new TextBox();
                            txtField.Bounds = new Rectangle(HPADDING, y, ClientSize.Width - 2 * HPADDING, 32);
                            txtField.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                            Controls.Add(txtField);
                            y += txtField.Height;
                            fieldControls[field.Attributes["StaticName"].Value] = txtField;
                            break;
                        case "DateTime":
                            DateTimePicker dtpField = new DateTimePicker();
                            dtpField.Bounds = new Rectangle(HPADDING, y, ClientSize.Width - 2 * HPADDING, 32);
                            dtpField.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                            Controls.Add(dtpField);
                            y += dtpField.Height;
                            fieldControls[field.Attributes["StaticName"].Value] = dtpField;
                            break;
                        case "Choice":
                            ComboBox cbField = new ComboBox();
                            cbField.Bounds = new Rectangle(HPADDING, y, ClientSize.Width - 2 * HPADDING, 32);
                            cbField.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                            Controls.Add(cbField);
                            foreach (XmlNode choice in field.SelectNodes("sp:CHOICES/sp:CHOICE", SPAdapter.Instance.NamespaceManager))
                            {
                                cbField.Items.Add(choice.InnerText);
                            }
                            XmlNode defaultChoice = field.SelectSingleNode("sp:Default", SPAdapter.Instance.NamespaceManager);
                            if (defaultChoice != null)
                            {
                                cbField.Text = defaultChoice.InnerText;
                            }
                            y += cbField.Height;
                            fieldControls[field.Attributes["StaticName"].Value] = cbField;
                            break;
                        case "Boolean":
                            CheckBox chkField = new CheckBox();
                            chkField.Bounds = new Rectangle(HPADDING, y, 32, 32);
                            chkField.Anchor = AnchorStyles.Top | AnchorStyles.Left;
                            Controls.Add(chkField);
                            y += chkField.Height;
                            fieldControls[field.Attributes["StaticName"].Value] = chkField;
                            break;
                        case "Lookup":
                            ComboBox lkField = new ComboBox();
                            lkField.Bounds = new Rectangle(HPADDING, y, ClientSize.Width - 2 * HPADDING, 32);
                            lkField.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                            lkField.ValueMember = "ID";
                            lkField.DisplayMember = "Name";
                            Controls.Add(lkField);
                            string showField = "ows_" + field.Attributes["ShowField"].Value;
                            foreach (XmlNode item in SPAdapter.Instance.GetListItems(field.Attributes["List"].Value, string.Empty)
                                .SelectNodes("rs:data/z:row", SPAdapter.Instance.NamespaceManager))
                            {
                                lkField.Items.Add(new ListItem
                                {
                                    ID = item.Attributes["ows_ID"].Value,
                                    Name = item.Attributes[showField].Value
                                });
                            }
                            y += lkField.Height;
                            fieldControls[field.Attributes["StaticName"].Value] = lkField;
                            break;
                        case "Number":
                            NumericUpDown nudField = new NumericUpDown();
                            nudField.Bounds = new Rectangle(HPADDING, y, ClientSize.Width - 2 * HPADDING, 32);
                            nudField.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                            Controls.Add(nudField);
                            y += nudField.Height;
                            fieldControls[field.Attributes["StaticName"].Value] = nudField;
                            break;
                        case "Currency":
                            TextBox crField = new TextBox();
                            crField.Bounds = new Rectangle(HPADDING, y, ClientSize.Width - 2 * HPADDING, 32);
                            crField.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                            crField.TextAlign = HorizontalAlignment.Right;
                            Controls.Add(crField);
                            y += crField.Height;
                            fieldControls[field.Attributes["StaticName"].Value] = crField;
                            break;
                        case "Note":
                            TextBox ntField = new TextBox();
                            ntField.Bounds = new Rectangle(HPADDING, y, ClientSize.Width - 2 * HPADDING, 100);
                            ntField.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                            ntField.Multiline = true;
                            Controls.Add(ntField);
                            y += ntField.Height;
                            fieldControls[field.Attributes["StaticName"].Value] = ntField;
                            break;
                        case "URL":
                            HyperlinkBox lnkField = new HyperlinkBox();
                            lnkField.Bounds = new Rectangle(HPADDING, y, ClientSize.Width - 2 * HPADDING, 32);
                            lnkField.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                            Controls.Add(lnkField);
                            y += lnkField.Height;
                            fieldControls[field.Attributes["StaticName"].Value] = lnkField;
                            break;
                        default:
                            txtField = new TextBox();
                            txtField.Bounds = new Rectangle(HPADDING, y, ClientSize.Width - 2 * HPADDING, 32);
                            txtField.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                            Controls.Add(txtField);
                            y += txtField.Height;
                            fieldControls[field.Attributes["StaticName"].Value] = txtField;
                            break;
                    }
                }
            }
            Cursor.Current = Cursors.Default;
        }

        private void miSave_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.OK;
        }

        private void miCancel_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            e.Cancel = DialogResult == DialogResult.OK && fieldControls.Any(pair => pair.Value is HyperlinkBox && !((HyperlinkBox)pair.Value).IsValid);
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);

            if (DialogResult == DialogResult.OK)
            {
                Cursor.Current = Cursors.WaitCursor;
                SPAdapter.Instance.AddNewItem(ListName,
                    from fc in fieldControls
                    select new KeyValuePair<string, string>(fc.Key, getControlValue(fc.Value)),
                    SiteUrl);
                Cursor.Current = Cursors.Default;
            }
        }

        private string getControlValue(Control control)
        {
            if (control is TextBox)
            {
                return control.Text;
            }
            else if (control is DateTimePicker)
            {
                return ((DateTimePicker)control).Value.ToString("s", DateTimeFormatInfo.InvariantInfo) + "Z";
            }
            else if (control is ComboBox)
            {
                return ((ComboBox)control).SelectedItem != null ? ((ComboBox)control).SelectedItem.ToString() : string.Empty;
            }
            else if (control is CheckBox)
            {
                return ((CheckBox)control).Checked.ToString();
            }
            else if (control is NumericUpDown)
            {
                return ((NumericUpDown)control).Value.ToString();
            }
            else
            {
                return control.Text;
            }
        }
    }
}